package com.wl.nio;

import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.time.LocalDateTime;
import java.util.Iterator;
import java.util.Scanner;

public class TestNonBlockingNIO {
    @Test
    public void client(){
        try {
            //获取通道
            SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
            //切换成非阻塞模式
            socketChannel.configureBlocking(false);
            //分配指定大小的缓冲区
            ByteBuffer buf = ByteBuffer.allocate(1024);
            //发送数据给客户端
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNext()){
                String str = scanner.next();
                buf.put((LocalDateTime.now().toString()+"\n"+str).getBytes());
                buf.flip();
                socketChannel.write(buf);
                buf.clear();
            }

            //关闭通道
            socketChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void server(){
        try {
            //获取通道
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            //切换非阻塞模式
            serverSocketChannel.configureBlocking(false);
            //绑定连接
            serverSocketChannel.bind(new InetSocketAddress(9898));
            //获取选择器
            Selector selector = Selector.open();
            //将通道注册到选择器上，并且指定“监听接受事件”
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

            //轮询的方式获取选择器上已经“准备就绪”的事件
            while (selector.select() > 0){
                //获取当前选择器中注册的“选择键（已经准备就绪的监听事件）”
                Iterator<SelectionKey> it = selector.selectedKeys().iterator();
                while (it.hasNext()){
                    //获取准备“就绪”的事件
                    SelectionKey sk = it.next();
                    //判断具体是什么事件准备就绪
                    if (sk.isAcceptable()){
                        //若“接受就绪”，获取客户端连接
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        //切换成非阻塞
                        socketChannel.configureBlocking(false);
                        //将该通道注册到选择器上
                        socketChannel.register(selector,SelectionKey.OP_READ);
                    }else if (sk.isReadable()){
                        //获取当前选择器上“读就绪”状态的通道
                        SocketChannel sChannel = (SocketChannel) sk.channel();
                        //读取数据
                        ByteBuffer buf = ByteBuffer.allocate(1024);

                        int len = 0;
                        while ((len = sChannel.read(buf))>0){
                            buf.flip();
                            System.out.println(new String(buf.array(),0,len));
                            buf.clear();
                        }
                    }
                    //取消选择键
                    it.remove();
                }
            }
            //关闭通道
            serverSocketChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
